%%HTML
<script src="require.js"></script>
%matplotlib inline
import math
import numpy as np, pandas as pd
import matplotlib.pyplot as plt, seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
import plotly.figure_factory as ff
pio.renderers.default='notebook'
pio.templates.default = "plotly_dark"
Deux fonctions pour faciliter la visualisation de données
def histo_critic(critic):
df = df_meta[df_meta['critic'] == critic]
fig = px.histogram(df, x="score",marginal='box',title='Répartition des notes pour '+critic)
fig.show()
def show_dev(developer):
tmp = df_games3.loc[df_games3['developer'] == developer, ['title', 'platform', 'score', 'score type','first_release']].groupby(['title', 'score type','first_release'])['score'].mean().reset_index().sort_values('first_release',ascending=True)
fig=px.histogram(tmp,x='title',y='score',color='score type',
category_orders={"score type":["meta","user"]},
barmode='group',
title='Comparaison des notes Méta et utilisateur pour les jeux de '+developer)
fig.show()
And further data manipulations. We will add some meaningful columns to the data frames (see comments in the code). Travail préparatoire
df_games = pd.read_csv('data/games.csv', lineterminator='\n')
df_games.drop(columns=['summary'], inplace=True)
# On construit 4 colonnes de plus | we add 4 more columnss
# - *meta_count* pour toutes les critiques de site web - for all "official" critics
# - *user_count* pour tous les avis utilisateurs - for all user reviews
# - *ratio* pour le rapport le nombre d'avis utilisateur par jeu / le nombre d'avis de sites - provides the #user review / # official reviews
# - *offset* pour exprimer la différence entre la note moyenne des critiques officielles et la note utilisateur moyenne - is the arithmetic difference between the average official review and the average user review
df_games['meta_count'] = (df_games['meta_pos'] + df_games['meta_mixed']+ df_games['meta_neg'])
df_games['user_count'] = (df_games['user_pos'] + df_games['user_mixed']+ df_games['user_neg'])
df_games['ratio'] = df_games['user_count'] / df_games['meta_count']
df_games['offset'] = df_games['meta_score'] - df_games['n_user_score']
# Réparation de la colonne "genre" pour en faire une liste avec des éléments uniques / we repair the "genre" column
df_games['genre']=df_games['genre'].apply(lambda x: x.replace('\'', ''))
df_games['genre'] = df_games.genre.apply(lambda x: x[1:-1].split(','))
df_games['genre']=df_games['genre'].apply(lambda x:list(set(x)))
# Réparation de la date / we repair the date
df_games['release_date'] = pd.to_datetime(df_games['release_date'])
df_games['month'] = df_games['release_date'].dt.month
df_games['year'] = df_games['release_date'].dt.year
# Ajout d'une date de première sortie pour un jeu
df_games['first_release'] = df_games.groupby('title')['release_date'].transform('min')
df_games2 = df_games.loc[(df_games['meta_overview'] != 'No score yet') & (df_games['user_overview'] != 'No user score yet') & (df_games['user_count'] != 0)]
df_games2.shape
(7377, 25)
On crée df_games2 qui ne contient que les jeux ayant à la fois une note globale utilisateur et une note globale de critique
We create df_games2 that only has games that have both a official critic and a user score.
df_games2
| title | platform | developer | genre | rating | release_date | meta_score | meta_overview | meta_pos | meta_mixed | ... | user_neg | n_user_score | real_date | meta_count | user_count | ratio | offset | month | year | first_release | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1001 Spikes | Wii U | Nicalis | [ Platformer, General, 2D, Action] | T | 2014-06-03 | 83 | Generally favorable reviews | 5 | 1 | ... | 6.0 | 70.0 | 2014-06-03 | 6 | 23.0 | 3.833333 | 13.0 | 6 | 2014 | 2014-06-03 |
| 5 | 3Souls | Wii U | Red Column | [ Platformer, 2D, Action Adventure, Action] | E10+ | 2016-07-28 | 49 | Generally unfavorable reviews | 0 | 3 | ... | 1.0 | 69.0 | 2016-07-28 | 4 | 7.0 | 1.750000 | -20.0 | 7 | 2016 | 2016-07-28 |
| 12 | A World of Keflings | Wii U | NinjaBee | [ General, Government, Breeding/Constructing... | E10+ | 2014-11-13 | 70 | Mixed or average reviews | 3 | 1 | ... | 1.0 | 76.0 | 2014-11-13 | 5 | 7.0 | 1.400000 | -6.0 | 11 | 2014 | 2014-11-13 |
| 14 | Abyss | Wii U | EnjoyUp Games | [ Platformer, General, 2D, Action] | E | 2014-05-01 | 59 | Mixed or average reviews | 0 | 6 | ... | 2.0 | 65.0 | 2014-05-01 | 7 | 12.0 | 1.714286 | -6.0 | 5 | 2014 | 2014-05-01 |
| 18 | Adventure Time: Explore the Dungeon Because I ... | Wii U | WayForward | [ Fantasy, Action Adventure, General] | E10+ | 2013-11-19 | 40 | Generally unfavorable reviews | 0 | 2 | ... | 11.0 | 57.0 | 2013-11-19 | 7 | 26.0 | 3.714286 | -17.0 | 11 | 2013 | 2013-11-19 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 31122 | Zombie Army Trilogy | Xbox One | Rebellion | [ Arcade, Shooter, Third-Person, Action] | M | 2015-03-06 | 62 | Mixed or average reviews | 2 | 7 | ... | 10.0 | 69.0 | 2015-03-06 | 10 | 53.0 | 5.300000 | -7.0 | 3 | 2015 | 2015-03-03 |
| 31127 | Zombie Driver: Ultimate Edition | Xbox One | EXOR Studios | [ Combat, General, Vehicle, Action, Simulat... | M | 2014-06-24 | 61 | Mixed or average reviews | 1 | 3 | ... | 5.0 | 61.0 | 2014-06-24 | 4 | 20.0 | 5.000000 | 0.0 | 6 | 2014 | 2014-06-24 |
| 31143 | Zoo Tycoon | Xbox One | Frontier Developments | [ Strategy, Management, Tycoon, Business / ... | E | 2013-11-22 | 68 | Mixed or average reviews | 12 | 32 | ... | 210.0 | 32.0 | 2013-11-22 | 45 | 323.0 | 7.177778 | 36.0 | 11 | 2013 | 2013-11-22 |
| 31144 | Zoo Tycoon: Ultimate Animal Collection | Xbox One | Asobo Studio | [ Compilation, Management, Strategy, Miscell... | E | 2017-10-31 | 70 | Mixed or average reviews | 2 | 4 | ... | 7.0 | 58.0 | 2017-10-31 | 6 | 20.0 | 3.333333 | 12.0 | 10 | 2017 | 2017-10-31 |
| 31146 | Zumba Fitness World Party | Xbox One | Zoe Mode | [Miscellaneous, Exercise / Fitness] | E | 2013-11-19 | 73 | Mixed or average reviews | 3 | 2 | ... | 15.0 | 62.0 | 2013-11-19 | 5 | 40.0 | 8.000000 | 11.0 | 11 | 2013 | 2013-11-05 |
7377 rows × 25 columns
df_meta=pd.read_csv('data/meta_reviews.csv',lineterminator='\n')
df_users=pd.read_csv('data/user_reviews.csv',lineterminator='\n')
df_games.shape, df_meta.shape, df_users.shape
((31147, 25), (163577, 6), (176912, 6))
# On ajoute à df_meta les colonnes offset (pour le jeu), avg_score et avg_offset (pour la publication)
# On ajoute aussi une colonne "num_critics" qui permet de voir directement le nombre de critiques publiées par ce site sur MC
df_meta2 = pd.merge(df_meta, df_games2[['title','platform', 'offset']], on=['title','platform'], how='right')
grouped = df_meta2.groupby('critic').agg(avg_score=('score', 'mean'), avg_offset=('offset', 'mean')).reset_index()
df_meta2 = pd.merge(df_meta2, grouped, on='critic', how='left')
critic_counts = df_meta2['critic'].value_counts()
df_meta2['num_critics'] = df_meta2['critic'].map(critic_counts)
df_games3 will be used to easily graph together average notes from critics and from users.
# On ajoute 2 nouvelles colonnes à df_games2 de manière à comparer plus facilement les notes critiques et utilisateurs
df_games3 = pd.concat([df_games2, df_games2], ignore_index=True)
df_games3["score"] = pd.concat([df_games2["meta_score"], df_games2["n_user_score"]], ignore_index=True)
df_games3["score type"] = ["meta"] * len(df_games2) + ["user"] * len(df_games2)
df_games3.shape
(14754, 27)
The df_critic2 table holds information about critics.
# Creation d'une nouvelle table "df_critics2" qui ne contient que les critiques
df_critics = df_meta2[['critic', 'avg_score', 'avg_offset','num_critics']].copy()
df_critics2 = df_critics.drop_duplicates(subset='critic', keep='first').sort_values(by='num_critics', ascending=False).reset_index(drop=True)
df_critics2
| critic | avg_score | avg_offset | num_critics | |
|---|---|---|---|---|
| 0 | Nintendo Life | 72.683240 | 1.677240 | 2333 |
| 1 | God is a Geek | 75.959801 | 5.449864 | 2214 |
| 2 | COGconnected | 75.983341 | 5.907450 | 2161 |
| 3 | Vandal | 76.605680 | 4.445531 | 2148 |
| 4 | NintendoWorldReport | 74.735407 | 1.844019 | 2090 |
| ... | ... | ... | ... | ... |
| 322 | Cynamite | 90.000000 | 3.000000 | 1 |
| 323 | IncGamers | 80.000000 | 0.000000 | 1 |
| 324 | Hooked Gamers | 79.000000 | 22.000000 | 1 |
| 325 | Glixel | 80.000000 | 8.000000 | 1 |
| 326 | Gamereactor Norway | 80.000000 | 14.000000 | 1 |
327 rows × 4 columns
Finalement, une table des développeurs
df_dev= pd.concat([df_games2.groupby('developer')['offset'].mean(),
df_games2.groupby('developer')['title'].count(),
df_games2.groupby('developer')['meta_score'].mean(),
df_games2.groupby('developer')['n_user_score'].mean(),
df_games2.groupby('developer')['ratio'].mean()],axis=1)
df_dev.columns = ['avg_offset','num_games','avg_meta','avg_user','avg_ratio']
df_dev=df_dev.reset_index()
#df_games.groupby('platform')['title'].count().sort_values(ascending=False).plot.bar(figsize=(10, 6), rot=0)
fig = px.histogram(df_games,x='platform',title="Nombre de titres présents par platforme",
color='platform',
category_orders={
"platform": ["3DS", "Wii U", "Switch", "PlayStation 4", "PlayStation 5","Xbox One","Xbox Series X"]
})
fig.show()
fig = px.histogram(df_games2,x='platform',title="Nombre de titres présents par platforme - avec notes meta + utilisateur",
color='platform',
category_orders={
"platform": ["3DS", "Wii U", "Switch", "PlayStation 4", "PlayStation 5","Xbox One","Xbox Series X"]
})
fig.show()
C'est sur ce dernier ensemnble que nous allons faire nos constats.
Par curiosité, on peut voir le cycle de vie des différentes plateformes, en regardant le nombre de jeux sortis par année. On regarde d'abord le nombre de fiches sur MC pour cette plateforme, par année, puis le nombre de fiches ayant des notes critiques et utilisateurs (donc encore une fois celles sur lesquelles on va pouvoir faire notre enquête plus poussée)
tmp = df_games.loc[(df_games['year'] < 2023) & (df_games['year'] > 2011) ].groupby(['year','platform']).count()['title'].reset_index()
fig = px.line(tmp, x='year',y='title',color='platform',
labels={
"title": "Nombre de jeux par console",
"year": "Année",
"platform": "Plateforme"
},
title='Nombre de titres par année de sortie - avec une fiche sur MC')
fig.show()
tmp = df_games2.loc[(df_games2['year'] < 2023) & (df_games2['year'] > 2011) ].groupby(['year','platform']).count()['title'].reset_index()
fig = px.line(tmp, x='year',y='title',color='platform',
labels={
"title": "Nombre de jeux par console",
"year": "Année",
"platform": "Plateforme"
},
title='Nombre de titres par année de sortie - avec une fiche sur MC et un note MC + utilisateur')
fig.show()
Juste pour s'amuser : à quoi resemble le cycle de sortie au cours d'une année (i.e on regarde le nombre de jeux sortis par mois, toutes années confondues, par console)
title_counts = df_games.loc[(df_games['year'] < 2023) & (df_games['year'] > 2011) ].groupby(['month','platform']).count()['title'].reset_index()
fig = go.Figure()
platforms = title_counts['platform'].unique()
for platform in platforms:
platform_data = title_counts[title_counts['platform'] == platform]
fig.add_trace(go.Scatter(x=platform_data['month'], y=platform_data['title'], mode='lines', name=platform))
# set plot title and axis labels
fig.update_layout(yaxis_title='Nombre de titres par console', xaxis_title='Mois', title='Nombre de titres par mois de sortie - avec fiche sur MC')
# show the plot
fig.show()
Ici un graphe qui montre la distribution des scores Meta pour chaque console. Ça se ressemble. Seule petite tendance qui se dégage : les consoles les plus récentes (Series X et PS5) ont une distribution de notes favorisant les notes hautes (sans doutes que le shovelware n'est pas encore arrivé !). (Pour information, la limite droite de chaque boite indique le 3ème quartile, c'est à dire que 25% des notes sont supérieures)
fig = px.box(df_games2,y='meta_score', x='platform',color='platform',hover_name='title',
title="Distribution des notes de site par plateforme",
category_orders={
"platform": ["3DS", "Wii U", "Switch", "PlayStation 4", "PlayStation 5","Xbox One","Xbox Series X"],
},
labels={
"title": "Nombre de jeux par console",
"meta_score": "Score Méta",
"platform": "Plateforme"
}
)
fig.show()
Regardons maintenant les notes utilisateurs moyenne pour chaque jeu de chaque plateforme. On voit que ça tire bien plus vers le bas !
fig = px.box(df_games2,y='n_user_score',x='platform',color='platform',hover_name='title',
title="Distribution des notes utilisateurs par plateforme",
category_orders={
"platform": ["3DS", "Wii U", "Switch", "PlayStation 4", "PlayStation 5","Xbox One","Xbox Series X"],
},
labels={
"title": "Nombre de jeux par console",
"n_user_score": "Score utilisateur",
"platform": "Plateforme"
},
)
fig.show()
Et représentons maintenant, pour chaque console, les distributions de notes Meta et des notes utilisateurs côte à côte pour se rendre compte de la situation... On dirait que plus la console est récente, plus les notes sont sévères. Ou alors les consoles nintendo sont relativement épargnées.
On voit notamment pour chaque console Sony et Microsoft que la médiane des notes utilisateur (le trait horizontal dans chaque boîte) est bien plus bas que pour les notes Méta.
fig = px.box(df_games3,y='score',x='platform',hover_name='title', color='score type',
title="Distribution des notes Meta par plateforme",
category_orders={
"platform": ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"],
},
labels={
"title": "Nombre de jeux par console",
"meta_score": "Score Méta",
"platform": "Plateforme"
}, )
fig.show()
fig = px.box(df_games2,y='offset',x='platform',hover_name='title',color='platform',
title="Offset des jeux par plateforme",
category_orders={
"platform": ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"],
},
labels={
"title": "Nombre de jeux par console",
"meta_score": "Score Méta",
"platform": "Plateforme"
}, )
fig.show()
Si l'on regarde, toutes consoles confondues, comment sont réparties les notes utilisateur moyennes et les notes MC moyennes pour chaque jeu, on voit deux distributions qui apparaissent décalées. On remarque aussi quelques points d'accumulation - par exemple la note "50%" semble souvent utilisée par la utilisateurs, mais pas spécialement par la critique. La note de 80% est aussi populaire chez les deux, et c'est d'ailleurs la plus courante pour les notes MC.
fig = px.histogram(df_games3,x='score',color='score type',
title="Distribution des notes meta et utilisateurs par jeu",
barmode="overlay",marginal="box",
labels={
"title": "Nombre de jeux par console",
"count": "quantité",
"platform": "Plateforme"
}, )
fig.show()
On affiche la distribution des ratios "nombre de critiques / nombre de revues utilisateur". On voit que la grande majorité des ratio est inférieure à 1, montrant qu'il y a plus de participation des utilisateurs. On pourrait parler du pic de la distribution (du mode) pour avoir une idée du ratio moyen.
hist_data=[df_games2['meta_score'],df_games2['n_user_score']]
group_labels = ['Score Meta','Score utilisateur']
fig = ff.create_distplot(hist_data, group_labels, bin_size=1,show_hist=False,show_rug=False)
fig.show()
fig = px.histogram(df_games2,x='offset',
title="Distribution de la différence entre la note Meta et la note utilisateur",
labels = {'count':'nombre de jeux'})
fig.add_shape(type="line",
x0=0, y0=0, x1=0, y1=350,
line=dict(color="red",width=1)
)
fig.show()
Ça penche à !droite Ça qui confirme ce qu'on a vu avant - il y a plus de jeux qui sont surestimés par la critique que l'inverse. Les notes utilisateurs sont en moyenne inférieur aux notes Critique.
Regardons maintenant par jeu. Ça risque d'être touffu, mais voici comment nous allons représenter cela.
Chaque point du graphe représente une jeu, sur une platefome.
La ligne blanche représente X=Y, c'est à dire que si un jeu a la même note utilisateur que critique, alors il sera sur cette ligne.
Ainsi, si un jeu a une note utilisateur inférieure à la note critique, il va se retrouver en dessous de la ligne blanche (et si c'est l'inverse, autrement dit les utilisateurs ont été plus généreux que les critiques, il sera au dessus de cette ligne blanche).
Comme attendu, on a plus de jeux en dessous qu'au dessus.
Intéressant aussi de regarder comment cela change en fonction des plateformes.
Enfin, j'ai ajouté une information : la taille du cerle représente le ratio entre le nombre de critique utilisateur et le nombre de critiques méta. Ce ratio est égal à 1 si on a le même nombre, et sera supérieur à 1 si il y a plus d'utilisateurs ayant laissé une note qu'il y a de notes de critiques. Le but de ce cercle est de montrer les cas de "review bombing", i.e. quand une armée d'utilisateurs se mettent à faire la revue d'un jeu.
fig=px.scatter(df_games2,x='meta_score',y='n_user_score', title = 'Notes utilisateur / Meta pour chaque jeu',
labels={
"n_user_score": "Score utilisateur",
"meta_score" : "Score Meta",
"platform" : "Plateforme"
},
color='platform', hover_data=['title'],size='ratio',trendline='ols',
category_orders={
"platform": ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"],
})
fig.add_shape(type="line",
x0=0, y0=0, x1=100, y1=100,
line=dict(color="white",width=2)
)
fig.show()
Voici d'ailleurs comment sont repartis les ratio : en général, on est proche de 1, mais il y a toute une franche de revue où les utilisateurs s'en sont donnés à coeur joie.
px.histogram(df_games2,x='ratio',title="distribution des ratios \"quantité de notes utilisateur\"/\"qtté de notes critique\"")
fig=px.scatter(df_games2[df_games2['ratio']>20],x='meta_score',y='n_user_score',title = 'Notes utilisateur / Meta pour chaque jeu avec Bombing > 20',
color='platform', hover_data=['title'],size='ratio',trendline='ols',
labels={
"n_user_score": "Score utilisateur",
"meta_score" : "Score Meta",
"platform" : "Plateforme"
},
category_orders={
"platform": ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"],
}
#animation_frame="year", animation_group="title"
)
fig.add_shape(type="line",
x0=0, y0=0, x1=100, y1=100,
line=dict(color="white",width=2)
)
#fig["layout"].pop("updatemenus")
fig.show()
fig = px.scatter(df_games2, x='release_date',y='meta_score', color='platform',trendline='ols',hover_data=['title'],
category_orders={
"platform": ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"],
},
title="Notes Meta au cours du temps, par plateforme"
)
fig.show()
On affiche maintenant le même graphe mais pour les notes utilisateurs. Comme on pouvait s'y attendre, les notes sont plus basses en moyenne.
En revanche, ce graphe montre quelque chose de fascinant : les points qui surnagent au dessus de la mélée sont des jeux assez... particuliers. On voit que ce n'est que pour certains jeux ou certaines séries (Dynasty Warrior par exemple) que les utilisateurs se donnent la peine de faire du bruit sur MC.
fig = px.scatter(df_games2, x='release_date',y='n_user_score', color='platform',trendline='ols',hover_data=['title'],
category_orders={
"platform": ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"],
},
title="Notes utilisateur au cours du temps, par plateforme")
fig.show()
fig = px.scatter(df_games2, x='release_date',y='offset', color='platform',trendline='ols',hover_data=['title'],
category_orders={
"platform": ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"],
},
title="Offset au cours du temps, par plateforme")
fig.show()
notemoyenne = df_games2.loc[(df_games2['year'] < 2023) & (df_games2['year'] > 2011) ].groupby(['year','platform']).mean()['meta_score'].reset_index()
fig = go.Figure()
for platform in ["3DS", "Wii U", "Switch","Xbox One","Xbox Series X", "PlayStation 4", "PlayStation 5"]:
platform_data = notemoyenne[notemoyenne['platform'] == platform]
fig.add_trace(go.Scatter(x=platform_data['year'], y=platform_data['meta_score'], mode='lines', name=platform))
# set plot title and axis labels
fig.update_layout(title='Note Critique moyenne par an et par console', xaxis_title='Année', yaxis_title='Note Critique',)
# show the plot
fig.show()
notemoyenne = df_games3.loc[(df_games3['year'] < 2023) & (df_games3['year'] > 2011) ].groupby(['year','score type']).mean()['score'].reset_index()
fig = px.line(notemoyenne,x='year',y='score',color='score type',title='Notes Meta et utilisateur moyennes par année')
fig.show()
notemoyenne = df_games3.loc[(df_games3['year'] < 2023) & (df_games3['year'] > 2011) ].groupby(['year','platform']).mean()['offset'].reset_index()
fig = px.line(notemoyenne,x='year',y='offset',color='platform',title='Offset moyen par plateforme, par année')
fig.show()
Et voici un graphe de tous les jeux en fonction de leur offset, au cours du temps.
En rouge, une droite de regression qui indique une tendance au cours du temps : la valeur du offset augmente (ce que montrait plus simplement le graphe précédent). En passant le curseur sur les points, on peut voir de quel jeu il s'agit.
fig = px.scatter(df_games2, x='release_date',y='offset', #color='platform',
trendline='ols',
trendline_color_override="red",
hover_data=['title','platform','meta_score','n_user_score'],
title='Offset pour chaque jeu au cours du temps')
fig.show()
Et voici la synthèse - évolution de l'offset moyen, tous jeux comfondus, par année.
On a vu dans les graphes précédents que ce paramêtre dépendait beaucoup des plateformes et du cycle de vie de ces dernières. On observe bien une tendance vers l'augmentation de ce derniers - i.e. des scores utilisateurs moyens qui ont tendance à être plus sévères que les scores des critiques.
notemoyenne = df_games3.loc[(df_games3['year'] < 2023) & (df_games3['year'] > 2011) ].groupby(['year']).mean()['offset'].reset_index()
notemoyenne2 = df_games3.loc[(df_games3['year'] < 2023) & (df_games3['year'] > 2011) ].groupby(['year']).std(ddof=0)['offset'].reset_index()
notemoyenne['std'] = notemoyenne2['offset']
fig = px.line(notemoyenne,x='year',y='offset',error_y='std',title='évolution du offset moyen par année, au cours du temps' )
fig.show()
On regarde combien de critiques sont produites par chaque organe identifié dans Metacritic. On comprend ici que Nintendo Life a produit 2333 critiques, God is a Geek Life 2214... Comme le montre la table ci dessous, nous avons 327 critiques officielles ayant émis au moins un avis
df_critics2
| critic | avg_score | avg_offset | num_critics | |
|---|---|---|---|---|
| 0 | Nintendo Life | 72.683240 | 1.677240 | 2333 |
| 1 | God is a Geek | 75.959801 | 5.449864 | 2214 |
| 2 | COGconnected | 75.983341 | 5.907450 | 2161 |
| 3 | Vandal | 76.605680 | 4.445531 | 2148 |
| 4 | NintendoWorldReport | 74.735407 | 1.844019 | 2090 |
| ... | ... | ... | ... | ... |
| 322 | Cynamite | 90.000000 | 3.000000 | 1 |
| 323 | IncGamers | 80.000000 | 0.000000 | 1 |
| 324 | Hooked Gamers | 79.000000 | 22.000000 | 1 |
| 325 | Glixel | 80.000000 | 8.000000 | 1 |
| 326 | Gamereactor Norway | 80.000000 | 14.000000 | 1 |
327 rows × 4 columns
Et voici comment se répartissent les critiques. En couleur, on montre la note moyenne (pas de tendance qui se dégage)
fig=px.bar(df_critics2,y='num_critics',color='avg_score',
hover_data=['critic'],
title='Combien de critiques chaque site a publié sur MC',
labels={
"num_critics": "Nombre de critiques"
})
fig.show()
On peut regarder, pour chaque critique, comment se répartissent leurs notes.
histo_critic('Gamekult')
histo_critic('Nintendo Life')
histo_critic('IGN')
On voit ici deux publications ayant choisi des notes tous les 10 points, et une autre (IGN) qui semble avoir un système hybride - ou peut être ayant changé.
Le graph suivant indique, pour chaque Critique (par exemple FNintendo, Gamekult...) la note moyenne récuppérée sur Metacritic vs l'offset moyen (c'est à dire la différence moyenne entre la note donnée aux jeux par la critique et la note donnée par les utilisateurs de Metacritique)
La taille des points indique le nombre de jeux évalués par cette critiques sur Metacritic.
On note un outlier interessant dans le coin inférieur gauche - GameKult qui a tendance à noter les jeux plutôt bas, et à être moins généreux que les utilisateurs. C'est rare ! On voit ici que le nuage de points est autour de l'axe x=5, ce qui montre qu'en général, les sites sont plus généreux de 5 points que les utilisateurs.
fig = px.scatter(df_critics2,x="avg_offset",y='avg_score',
size='num_critics',
hover_data=['critic'],
title = 'Score moyen vs. offset moyen pour chaque publication',
labels={
"avg_offset": "Offset moyen",
"avg_score": "Note moyenne",
"num_critics": "Nombre de critiques"
})
fig.show()
2660 développeurs dans la base, le plus prolifique étant Capcom. Gardons en tête que chaque console est comptée individuellement (donc un jeu sorti sur 4 consoles est compté 4 fois), et que certains développeurs ont changé de nom au cours du temps (UbiSoft, EA Sports...)
df_games2.groupby('developer')['title'].count().sort_values(ascending=False).reset_index()
| developer | title | |
|---|---|---|
| 0 | Capcom | 119 |
| 1 | Telltale Games | 108 |
| 2 | Square Enix | 70 |
| 3 | Nintendo | 63 |
| 4 | Bandai Namco Games | 53 |
| ... | ... | ... |
| 2655 | Kluge Interactive | 1 |
| 2656 | Klace | 1 |
| 2657 | Kite Games | 1 |
| 2658 | KissAssociates, Kiss | 1 |
| 2659 | yeo | 1 |
2660 rows × 2 columns
Voici le même tableau, en séparant par plateforme.
df_games2.groupby(['developer','platform']).count()['title'].sort_values(ascending=False).reset_index()
| developer | platform | title | |
|---|---|---|---|
| 0 | Telltale Games | PlayStation 4 | 53 |
| 1 | Telltale Games | Xbox One | 49 |
| 2 | Capcom | PlayStation 4 | 41 |
| 3 | Square Enix | PlayStation 4 | 31 |
| 4 | Nintendo | Switch | 29 |
| ... | ... | ... | ... |
| 4605 | Herobeat Studios | Switch | 1 |
| 4606 | Herobeat Studios | Xbox One | 1 |
| 4607 | HexaDrive | PlayStation 4 | 1 |
| 4608 | HexaDrive | Xbox One | 1 |
| 4609 | yeo | Switch | 1 |
4610 rows × 3 columns
Regardons par exemple tous les titres de From Software
df_games2.loc[df_games2['developer'] == 'From Software', 'title'].reset_index(drop=True)
0 Bloodborne 1 Bloodborne: The Old Hunters 2 Dark Souls II: Scholar of the First Sin 3 Dark Souls III 4 Dark Souls III: Ashes of Ariandel 5 Dark Souls III: The Ringed City 6 Dark Souls Remastered 7 Deracine 8 Sekiro: Shadows Die Twice 9 Elden Ring 10 Elden Ring 11 Dark Souls Remastered 12 Dark Souls II: Scholar of the First Sin 13 Dark Souls III 14 Dark Souls III: Ashes of Ariandel 15 Dark Souls III: The Ringed City 16 Dark Souls Remastered 17 Sekiro: Shadows Die Twice Name: title, dtype: object
On peut regarder les développeurs ayant les plus forts offset, c'est à dire le plus grand décallage moyens pour leurs jeux entre la note Meta et la note utilisateur.
df_dev.sort_values(by='avg_offset',ascending=False)
| developer | avg_offset | num_games | avg_meta | avg_user | avg_ratio | |
|---|---|---|---|---|---|---|
| 2381 | Twice Circled | 62.0 | 1 | 78.0 | 16.0 | 1.250000 |
| 689 | Electronic Arts, EA Tiburon | 59.0 | 1 | 79.0 | 20.0 | 5.590909 |
| 288 | Blizzard Entertainment, Digital Eclipse | 57.0 | 1 | 75.0 | 18.0 | 1.142857 |
| 1824 | Red Cerberus | 55.0 | 1 | 82.0 | 27.0 | 6.909091 |
| 1030 | Huge Calf Studios | 55.0 | 1 | 72.0 | 17.0 | 0.750000 |
| ... | ... | ... | ... | ... | ... | ... |
| 2051 | Snowrunner Games | -31.0 | 1 | 30.0 | 61.0 | 3.444444 |
| 1900 | RunicCodes | -31.0 | 1 | 35.0 | 66.0 | 1.400000 |
| 1021 | Hoplite Research | -32.0 | 2 | 38.0 | 70.0 | 2.625000 |
| 1947 | Samustai | -42.0 | 1 | 41.0 | 83.0 | 1.000000 |
| 2125 | Square Enix, ilinx inc. | -45.0 | 1 | 37.0 | 82.0 | 6.153846 |
2660 rows × 6 columns
Un peu comme les jeux plus tot, regardons les développeurs - note Meta moyenne vs. note utilisateur moyenne, en affichant leur 'ratio' moyen (c'est à dire à quel point les revues pour ce développeurs sont susceptibles de recevoir un afflux d'utilisateurs)
fig=px.scatter(df_dev[df_dev['num_games']>1],x='avg_meta',y='avg_user', title = 'Notes utilisateur / Meta moyenne pour chaque développeur',
labels={
"avg_user": "Score utilisateur",
"avg_meta" : "Score Meta",
"developer" : "Developeur"
},
hover_data=['developer'],
size='avg_ratio',
)
fig.add_shape(type="line",
x0=0, y0=0, x1=100, y1=100,
line=dict(color="white",width=2)
)
fig.show()
Regardons l'évolution des notes Méta et utilisateurs pour les titres de certaines compagnies.
show_dev('From Software')
show_dev('EA Sports')
show_dev('Ubisoft Montreal')
show_dev('Electronic Arts')
show_dev('Eidos Montreal')
show_dev('Naughty Dog')